
import UIKit

public protocol RLSegmentViewDelegate: class {
    
    /// Asks the data source to return the number of buttons in the segment view.
    ///
    /// - parameter segmentView: An object representing the segment view requesting this information.
    ///
    /// - returns: The number of buttons in segmentView. The default value is 0.
    func numberOfButtonsInSegmentView(_ segmentView: RLSegmentView) -> Int
    
    /// Asks the data source for a button to insert in a particular location of the segment view.
    ///
    /// - parameter segmentView: A segment-view object requesting the button.
    /// - parameter index:       An index locating a button in segmentView.
    ///
    /// - returns: An object inheriting from UIButton that the segment view can use for the specified index.
    func segmentView(_ segmentView: RLSegmentView, buttonForSegmentAt index: Int) -> UIButton
    
    /// Tells the delegate that a button is about to be selected or not for a particular index.
    ///
    /// - parameter segmentView: A segment-view object informing the delegate about the new button state changed.
    /// - parameter index:       An index locating the new state changed button in segmentView.
    /// - parameter selected:    A bool tells the button is selected or not
    func segmentView(_ segmentView: RLSegmentView, change button: UIButton, stateAt index: Int, selected: Bool)
    
    
    /// Tells the delegate that a button is about to be selected for a particular index.
    ///
    /// - parameter segmentView: A segment-view object informing the delegate about the new button selected.
    /// - parameter index:       An index locating the new selected button in segmentView.
    func segmentView(_ segmentView: RLSegmentView, changeSegmentAt index: Int)
    
}

public class RLSegmentView: UIView {

    internal var buttonMaps = [Int: UIButton]()
    internal var buttonWidth: CGFloat = 0
    internal var selectedIndex: Int = 0
    
    public var backgroundView: UIView?
    public var showIndicator: Bool = true
    public var indicatorView: UIView?
    public var showLineView: Bool = true
    public var lineViewColor: UIColor = .blue
    /// Width of the line view
    public var lineWidth: CGFloat = 1.0
    /// Height percent of the line view
    public var lineHeight: CGFloat = 0.7
    public weak var delegate: RLSegmentViewDelegate?
    public var noneStyleIndex: Int?
    public func setSelectedIndex(index: Int) {
        
        if (self.delegate != nil){
            self.delegate?.segmentView(self, changeSegmentAt: index)
        }
        
        selectedIndex = index
        
        if noneStyleIndex == nil || index != noneStyleIndex {
            layoutIndicator(true)
            refreshButtonState()
        }
    }

    public func scrollOffsetRatio(_ ratio: Float) {
        
    }
    
    public func initButtons() {

        if let backgroundView = self.backgroundView {
            backgroundView.frame = self.frame
            self.addSubview(backgroundView)
        }
        
        let buttonCount = numberOfButtons()
        self.buttonWidth = buttonCount > 0 ? self.bounds.width / CGFloat(buttonCount) : self.bounds.width
        
        let contentSize = self.bounds.size
        for i in 0..<buttonCount {
            
            if let button = buttonFor(index: i) {
                
                button.frame = CGRect(x: self.buttonWidth * CGFloat(i), y: 0, width: self.buttonWidth, height: contentSize.height - 1)
                button.tag = i
                button.addTarget(self, action: #selector(RLSegmentView.buttonTapped(_:)), for: .touchUpInside)
                
                self.buttonMaps[i] = button
                self.addSubview(button)

            }
        }
        
        if showLineView {
            
            for i in 0..<buttonCount-1 {
                
                let height = self.bounds.height * lineHeight
                let width: CGFloat = lineWidth
                let lineView = UIView(frame: CGRect(x: self.buttonWidth * CGFloat(i + 1) - width/2, y: (self.bounds.height - height) / 2, width: width, height: height))
                lineView.backgroundColor = self.lineViewColor
                self.addSubview(lineView)
            }
            
        }
        
        layoutIndicator(false)
        
    }
    
}


// MARK: Internal Functions

extension RLSegmentView {
    
    func numberOfButtons() -> Int {
        
        if (self.delegate != nil), let number = self.delegate?.numberOfButtonsInSegmentView(self) {
            return number
        } else {
            return 0
        }
    }
    
    func buttonFor(index: Int) -> UIButton? {
        
        if (self.delegate != nil), let button = self.delegate?.segmentView(self, buttonForSegmentAt: index) {
            return button
        } else {
            return nil
        }
    }
    
    @objc func buttonTapped(_ sender: UIButton) {
    
        setSelectedIndex(index: sender.tag)
        
    }
    
    func refreshButtonState() {
        
        for (index, button) in self.buttonMaps {
            self.delegate?.segmentView(self, change: button, stateAt: index, selected: (index == self.selectedIndex))
        }
    }
    
    func layoutIndicator(_ animate: Bool) {
        
        if showIndicator, let indicatorView = self.indicatorView {
            
            indicatorView.autoresizingMask = UIView.AutoresizingMask(rawValue: UInt(0x3f))
            self.addSubview(indicatorView)
            self.sendSubviewToBack(indicatorView)
            
            let button = self.buttonMaps[self.selectedIndex]!
            
            button.setNeedsLayout()
            button.layoutIfNeeded()
            
            let frame = button.frame
            let titleFrame = button.titleLabel!.frame
            if animate {
                UIView.animate(withDuration: 0.15, animations: {
                    indicatorView.frame = CGRect(x: frame.origin.x + titleFrame.origin.x, y: self.bounds.height - indicatorView.bounds.height, width: titleFrame.width, height: indicatorView.bounds.height)
                })
            } else {
                indicatorView.frame = CGRect(x: frame.origin.x + titleFrame.origin.x, y: self.bounds.height - indicatorView.bounds.height, width: titleFrame.width, height: indicatorView.bounds.height)
            }
        }
    }
    
}



